package cn.aihongbo.test.shake

import android.app.Activity
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
import android.graphics.PixelFormat
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.IBinder
import androidx.core.app.NotificationCompat
import java.io.File
import java.io.FileOutputStream
import kotlin.random.Random


/**
 * Created by ZhaoHongBo on 2025/11/4.
 * Copyright (c) 2025 ZHB. All rights reserved.
 */

const val H_SCREEN_CAPTURE_CHANNEL_ID = "h_screen_capture"
const val H_FILE_CAPTURE_PARENT = "capture"

class ScreenCaptureService : Service() {

    private var mProjectionManager: MediaProjectionManager? = null
    private var mMediaProjection: MediaProjection? = null
    private var mVirtualDisplay: VirtualDisplay? = null
    private val VIRTUAL_DISPLAY_NAME: String = "ScreenCapture"
    private var mImageReader: ImageReader? = null

    private val mediaProjectionReceiver: BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val fileParent = File(filesDir.absolutePath, H_FILE_CAPTURE_PARENT)
            if (!fileParent.exists()) {
                fileParent.mkdir()
            }
            val localFile = File(
                fileParent.absolutePath, "${System.currentTimeMillis()}.png"
            )
            saveScreenCaptureMat(localFile)

            sendBroadcast(Intent("H_SCREEN_CAPTURE_RESULT").apply {
                putExtra("image", localFile.absolutePath)
            })
        }
    }

    override fun onCreate() {
        super.onCreate()
        createNotificationChannel()
        val filter = IntentFilter("ACTION_MEDIA_PROJECTION_PERMISSION")
        registerReceiver(mediaProjectionReceiver, filter, RECEIVER_EXPORTED)
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(mediaProjectionReceiver)
    }

    private fun createNotificationChannel() {
        val channel = NotificationChannel(
            H_SCREEN_CAPTURE_CHANNEL_ID, "屏幕捕获服务", NotificationManager.IMPORTANCE_DEFAULT
        )
        val manager: NotificationManager? = getSystemService(NotificationManager::class.java)
        manager?.createNotificationChannel(channel)
    }

    private fun startForegroundService() {
        val intent = Intent(this, MainActivity::class.java)
        val contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
        val notification = NotificationCompat.Builder(this, H_SCREEN_CAPTURE_CHANNEL_ID)
            .setContentTitle("屏幕捕获中").setContentText("应用正在捕获屏幕，您可以在此处查看信息")
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setPriority(NotificationCompat.PRIORITY_HIGH).setContentIntent(contentIntent)
            .setOngoing(true).setVisibility(NotificationCompat.VISIBILITY_PUBLIC).build()
        startForeground(Random.nextInt(), notification)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val resultCode: Int? = intent?.getIntExtra("resultCode", Activity.RESULT_CANCELED)
        val data: Intent = intent?.getParcelableExtra("data", Intent::class.java) as Intent

        startForegroundService()

        mProjectionManager = getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager?
        mMediaProjection = mProjectionManager?.getMediaProjection(resultCode ?: 0, data)
        setupVirtualDisplay()

        return START_STICKY
    }

    private fun setupVirtualDisplay() {
        val displayMetrics = resources.displayMetrics
        mImageReader = ImageReader.newInstance(
            displayMetrics.widthPixels, displayMetrics.heightPixels, PixelFormat.RGBA_8888, 2
        )
        mMediaProjection?.registerCallback(object : MediaProjection.Callback() {}, null)
        mVirtualDisplay = mMediaProjection?.createVirtualDisplay(
            VIRTUAL_DISPLAY_NAME,
            displayMetrics.widthPixels,
            displayMetrics.heightPixels,
            displayMetrics.densityDpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            mImageReader?.surface,
            null,
            null
        )
    }

    fun saveScreenCaptureMat(localFile: File) {
        try {
            val image = mImageReader?.acquireLatestImage()
            if (image != null) {
                val planes = image.planes
                val buffer = planes[0].buffer
                val pixelStride = planes[0].pixelStride
                val rowStride = planes[0].rowStride
                val rowPadding = rowStride - pixelStride * (mImageReader?.width ?: 0)

                val bitmap: Bitmap = Bitmap.createBitmap(
                    (mImageReader?.width ?: 0) + rowPadding / pixelStride,
                    mImageReader?.height ?: 0,
                    Bitmap.Config.ARGB_8888
                )
                bitmap.copyPixelsFromBuffer(buffer)

                //写文件
                val os = FileOutputStream(localFile)
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, os)
                os.flush()
                bitmap.recycle()
            }
            image?.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }
}